﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web;

namespace mForum.Web.Common.Infrastructure.AssetManager
{
    using mForum.Core.Infrastructure.IoC;

    public class PostprocessingModule : IHttpModule
    {
        public class SubstitutionStream : Stream
        {
            private Stream _wrappedStream;
            private IHttpContextProvider _httpContextProvider;
            private IAssetManager _assetManager;

            public SubstitutionStream(Stream wrappedStream, IHttpContextProvider httpContextProvider, IAssetManager assetManager)
            {
                _wrappedStream = wrappedStream;
                _httpContextProvider = httpContextProvider;
                _assetManager = assetManager;
            }

            public override void Flush()
            {
                _wrappedStream.Flush();
            }

            public override long Seek(long offset, SeekOrigin origin)
            {
                return _wrappedStream.Seek(offset, origin);
            }

            public override void SetLength(long value)
            {
                throw new NotSupportedException();
            }

            public override int Read(byte[] buffer, int offset, int count)
            {
                throw new NotSupportedException();
            }

            public override void Write(byte[] buffer, int offset, int count)
            {
                if (_httpContextProvider.Response.ContentType != "text/html")
                {
                    _wrappedStream.Write(buffer, offset, count);
                    return;
                }

                var page = new StringBuilder(Encoding.UTF8.GetString(buffer, offset, count));

                foreach(var type in AssetType.AssetTypeDictionary)
                {
                    page.Replace(String.Format("#{0}_REFERENCE#", type.Key.ToUpper()), _assetManager.GetAssetReference(type.Key));
                }

                var transformedPageBytes = Encoding.UTF8.GetBytes(page.ToString());
                _wrappedStream.Write(transformedPageBytes, 0, transformedPageBytes.Length);
            }

            public override bool CanRead
            {
                get { return false; }
            }

            public override bool CanSeek
            {
                get { return true; }
            }

            public override bool CanWrite
            {
                get { return true; }
            }

            public override long Length
            {
                get { throw new NotSupportedException(); }
            }

            public override long Position
            {
                get { throw new NotSupportedException(); }
                set { throw new NotSupportedException(); }
            }
        }

        private HttpApplication _application;

        public void Dispose()
        {
        }

        public void Init(HttpApplication context)
        {
            context.BeginRequest += context_BeginRequest;
            _application = context;
        }

        void context_BeginRequest(object sender, EventArgs e)
        {
            _application.Response.Filter = new SubstitutionStream(_application.Response.Filter,
                IoC.GetInstance<IHttpContextProvider>(), IoC.GetInstance<IAssetManager>());
        }
    }
}
                                                               